using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Utilities;



namespace Services.Menu
{
    public class ItemsListComponent : OrientableScreen
    {
        SpriteBatch spritebatch;
        InputManager input_manager;
        protected MyButton title;
        protected MyButton upper_box, lower_box;

        protected Action<String> closeSelector;
        Action abortSelection;
        String titleString;
        protected ArrayList<MyButton> list;
        protected Texture2D white, confirm, cancel, circle;

        protected Rectangle dragArea;

        public SpriteFont font, titleFont, smallFont;
        bool isThereTextArea;
        bool isThereTextArea2;
        String defaultString;
       
        ArrayList<String> itemsList;
        ArrayList<String> itemsList2;
        String keyboardTitle, keyboardDesc;
        bool editingList;
        bool openPopUp;
        string selectedItem;
        MyButton titleEdit;
        MyButton itemEdit;
        MyButton confirmEdit;
        MyButton cancelEdit;
        TextPos textPos;
        TextPos textPos2;
        bool setEmptyTextArea;
        string editableString;
        string text2;
        bool allow_custom_keyboard = false;
        List<ShortCut> ShortCuts = new List<ShortCut>();
        #region Constructors
        public ItemsListComponent(Game game, Action<String> closeSelector, Action abortSelection, String titleString,
            ArrayList<String> itemsList, TextPos textPos)
            : base(game)
        {
            this.closeSelector = closeSelector;
            this.titleString = titleString;
            this.abortSelection = abortSelection;
            defaultString = "";
            isThereTextArea = false;
            this.itemsList = itemsList;
            editingList = false;
            openPopUp = false;
            this.textPos = textPos;
            this.itemsList2 = new ArrayList<string>();
        }
        public ItemsListComponent(Game game, Action<String> closeSelector, Action abortSelection, String titleString,
            ArrayList<String> itemsList, ArrayList<String> itemsList2, TextPos textPos, TextPos textPos2, SpriteFont font)
            : base(game)
        {
            this.closeSelector = closeSelector;
            this.titleString = titleString;
            this.abortSelection = abortSelection;
            defaultString = "";
            isThereTextArea = false;
            isThereTextArea2 = false;
            this.itemsList = itemsList;
            this.itemsList2 = itemsList2;
            editingList = false;
            openPopUp = false;
            this.textPos = textPos;
            this.textPos2 = textPos2;
            this.font = font;
        }
        public ItemsListComponent(Game game, Action<String> closeSelector, Action abortSelection, String titleString,
            ArrayList<String> itemsList, string defaultString, string keyboardTitle, string keyboardDesc, TextPos textPos,
            bool setEmptyTextArea, string editableString, string text2, bool allow_custom_keyboard, List<ShortCut> ShortCuts)
            : this(game, closeSelector, abortSelection, titleString, itemsList, textPos)
        {//a
            this.defaultString = defaultString;
            isThereTextArea = true;
            isThereTextArea2 = true;
            this.text2 = text2;
            this.keyboardDesc = keyboardDesc;
            this.keyboardTitle = keyboardTitle;
            this.setEmptyTextArea = setEmptyTextArea;
            this.editableString = editableString;
            this.itemsList2 = new ArrayList<string>();
            this.allow_custom_keyboard = allow_custom_keyboard;
            this.ShortCuts = ShortCuts;
        }
        public ItemsListComponent(Game game, Action<String> closeSelector, Action abortSelection, String titleString,
            ArrayList<String> itemsList, string defaultString, string keyboardTitle, string keyboardDesc, TextPos textPos,
            bool setEmptyTextArea, string editableString, bool allow_custom_keyboard, List<ShortCut> ShortCuts)
            : this(game, closeSelector, abortSelection, titleString, itemsList, textPos)
        {//a
            this.defaultString = defaultString;
            isThereTextArea = true;
            isThereTextArea2 = false;
            //this.text2 = text2;
            this.keyboardDesc = keyboardDesc;
            this.keyboardTitle = keyboardTitle;
            this.setEmptyTextArea = setEmptyTextArea;
            this.editableString = editableString;
            this.itemsList2 = new ArrayList<string>();
            this.allow_custom_keyboard = allow_custom_keyboard;
            this.ShortCuts = ShortCuts;
        }
        public ItemsListComponent(Game game, String titleString, ArrayList<String> itemsList, string confirmString,
            Action<String> EditItem, Action abortSelection, TextPos textPos)
            : this(game, EditItem, abortSelection, titleString, itemsList, textPos)
        {
            this.defaultString = confirmString;
            isThereTextArea = false;
            isThereTextArea2 = false;
            editingList = true;
            openPopUp = false;
            this.itemsList2 = new ArrayList<string>();
        }
        public ItemsListComponent(Game game, String titleString, ArrayList<String> itemsList, ArrayList<String> itemsList2, string confirmString,
            Action<String> EditItem, Action abortSelection, TextPos textPos, TextPos textPos2, SpriteFont font)
            : this(game, EditItem, abortSelection, titleString, itemsList, textPos)
        {
            this.defaultString = confirmString;
            isThereTextArea = false;
            isThereTextArea2 = false;
            editingList = true;
            openPopUp = false;
            this.itemsList2 = itemsList2;
            this.textPos2 = textPos2;
            this.font = font;
        }
        #endregion

        public override void Initialize()
        {
            spritebatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

            input_manager = new InputManager(Game);
            Game.Components.Add(input_manager);
            input_manager.OnTap += on_tap;
            input_manager.OnDrag += on_drag;
            input_manager.OnHorizontalDrag += on_drag;
            input_manager.OnVerticalDrag += on_drag;
            input_manager.OnDragCompleted += on_drag_completed;

            //screen_transform = Game.ScreenTransformMatrix(graphics);
            //if (font == null)
                font = Game.Content.Load<SpriteFont>("ItemSelector\\font");
            smallFont = Game.Content.Load<SpriteFont>("ItemSelector\\small");
            titleFont = Game.Content.Load<SpriteFont>("ItemSelector\\font");
            //small = Game.Content.Load<SpriteFont>("ItemSelector\\small");
            white = Game.Content.Load<Texture2D>("ItemSelector\\whitepixel");
            circle = Game.Content.Load<Texture2D>("ItemSelector\\circle");
            confirm = Game.Content.Load<Texture2D>("ItemSelector\\delete");
            cancel = Game.Content.Load<Texture2D>("ItemSelector\\cancel");


            list = new ArrayList<MyButton>();
            dragging = false;
            base.Initialize();
            if (isThereTextArea && !isThereTextArea2 && itemsList.Count == 0)
                if (!allow_custom_keyboard)
                {
                    OpenKeyboard();
                }
                else
                {
                    open_custom_keyboard = true;
                }
        }
        bool open_custom_keyboard = false;
        public void CloseCustomKeyboard(string result)
        {
            Game.Components.Remove(input_manager);
            Game.Components.Remove(this);
            closeSelector(result);
        }
        public void AbortCustomKeyboard()
        {
            //Game.Components.Remove(input_manager);
            //Game.Components.Remove(this);
            Game.Components.Add(input_manager);
            //abortSelection();
        }
        //protected override void ChangeOrientation()
        //{

        //    int offset = 0;
        //    if(list.Count>0)
        //        if (prev_orientation == DisplayOrientation.LandscapeLeft || prev_orientation == DisplayOrientation.LandscapeRight)
        //            offset = 240 - list[0].rectangle.Y;
        //        else
        //            offset = 400 - list[0].rectangle.Y;
        //    base.ChangeOrientation();
        //    if (list.Count > 0)
        //        for (int i = 0; i < list.Count; i++)
        //            list[i].rectangle.Y += offset;
        //}
        bool dragging;
        float prev_velocity;
        public override void Update(GameTime gameTime)
        {
            if (open_custom_keyboard)
            {
                Game.Components.Remove(input_manager);
                Game.Components.Add(new CustomKeyboard(Game, CloseCustomKeyboard, AbortCustomKeyboard, titleString, "", ShortCuts));
                open_custom_keyboard = false;
                return;
            }
            float dt = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (velocity != 0 && !dragging)
            {
                prev_velocity = velocity;
                if (velocity < 0)
                {
                    velocity += dt * 4;
                    if (velocity > 0)
                        velocity = 0;
                }
                else
                {
                    velocity -= dt * 4;
                    if (velocity < 0)
                        velocity = 0;
                }
                //if (Math.Abs(velocity) < 0.5f)
                //    velocity = 0;
                var delta_y = (int)velocity;
                //if (dragging)
                //{

                if (list.Count > 0 && list[0].rectangle.Y > dragArea.Y)
                {
                    velocity = 0;
                    delta_y = dragArea.Y - list[0].rectangle.Y;
                }
                else if (list.Count > 0 && list[list.Count - 1].rectangle.Y + list[list.Count - 1].rectangle.Height < dragArea.Y + dragArea.Height)
                {
                    velocity = 0;
                    delta_y = dragArea.Y + dragArea.Height - list[list.Count - 1].rectangle.Y - list[list.Count - 1].rectangle.Height;
                    if (list[0].rectangle.Y + delta_y > dragArea.Y)
                    {
                        delta_y = dragArea.Y - list[0].rectangle.Y;
                    }
                }
                for (int i = 0; i < list.Count; i++)
                {
                    list[i].rectangle.Y += delta_y;
                    list[i].UpdateTextPos();
                    /*if (list[i].textPos == TextPos.Left && list[i].position!=null)
                    {
                        list[i].position.Y += 20;
                    }
                    if (list[i].textPos2 == TextPos.Left && list[i].position2!=null)
                    {
                        list[i].position2.Y += 20;
                    }*/
                }
                //if (list.Count > 0 && list[0].rectangle.Y > dragArea.Y && list[list.Count - 1].rectangle.Y + list[list.Count - 1].rectangle.Height < dragArea.Y + dragArea.Height)
                //{
                //    velocity = 0;
                //    delta_y = dragArea.Y - list[0].rectangle.Y;
                //    for (int i = 0; i < list.Count; i++)
                //    {
                //        list[i].rectangle.Y += delta_y;
                //        list[i].UpdateTextPos();
                //    }
                //}
                //}
            }
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed && Game.Components.Contains(input_manager))
            {
                if (editingList && openPopUp)
                {
                    openPopUp = false;
                }
                else
                {
                    Game.Components.Remove(input_manager);
                    Game.Components.Remove(this);
                    abortSelection();
                }
            }
            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            //spritebatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, screen_transform);
            spritebatch.Begin();
            if (!openPopUp)
            {
                for (int i = 0; i < list.Count; i++)
                    list[i].Draw(spritebatch);

                upper_box.Draw(spritebatch);
                lower_box.Draw(spritebatch);
                title.Draw(spritebatch);
            }
            else
            {
                titleEdit.Draw(spritebatch);
                itemEdit.Draw(spritebatch);
                confirmEdit.Draw(spritebatch);
                cancelEdit.Draw(spritebatch);
            }
            //confirm.Draw(spritebatch);
            //cancel.Draw(spritebatch);
            spritebatch.End();

            base.Draw(gameTime);
        }
        void on_tap(Vector2 tap_pos)
        {
            if (press_wait < PRESS_INTERVAL) return;
            if (editingList)
            {
                if (openPopUp)
                {
                    if (confirmEdit.tapped_on(tap_pos))
                    {
                        Game.Components.Remove(input_manager);
                        Game.Components.Remove(this);
                        openPopUp = false;
                        closeSelector(selectedItem);
                        //selectedItem = "";
                        //ChangeOrientation();
                        return;
                    }
                    else if (cancelEdit.tapped_on(tap_pos))
                    {
                        openPopUp = false;
                        selectedItem = "";
                        titleEdit.text = defaultString;
                        return;
                    }
                }
                else
                {
                    int start = 0;
                    if (isThereTextArea2)
                        start = 2;
                    else if (isThereTextArea)
                        start = 1;
                    for (int i = start; i < list.Count; i++)
                        if (list[i].tapped_on(tap_pos) && !list[i].rectangle.Intersects(lower_box.rectangle))
                        {
                            var s = list[i].text + ((list[i].text2 != null && list[i].text2 != "") ? " " + list[i].text2 : "");
                            ExitSelector(s);
                            //ExitSelector(list[i].text);
                            break;
                        }
                }
            }
            else
            {
                if (isThereTextArea)
                {
                    if (list[0].tapped_on(tap_pos) && !list[0].rectangle.Intersects(lower_box.rectangle))
                    {
                        if (!allow_custom_keyboard)
                        {
                            OpenKeyboard();
                        }
                        else
                        {
                            Game.Components.Remove(input_manager);
                            //Game.Components.Remove(this);
                            Game.Components.Add(new CustomKeyboard(Game, CloseCustomKeyboard, AbortCustomKeyboard, titleString, "", ShortCuts));
                        }
                        return;
                    }
                }
                if (isThereTextArea2)
                    if (list[1].tapped_on(tap_pos) && !list[1].rectangle.Intersects(lower_box.rectangle))
                        ExitSelector(list[1].text);
                int start = 0;
                if (isThereTextArea2)
                    start = 2;
                else if (isThereTextArea)
                    start = 1;
                for (int i = start; i < list.Count; i++)
                    if (list[i].tapped_on(tap_pos) && !list[i].rectangle.Intersects(lower_box.rectangle))
                    {
                        var s = list[i].text + ((list[i].text2 != null && list[i].text2 != "") ? " " + list[i].text2 : "");
                        ExitSelector(s);
                        break;
                    }
            }
        }

        void OpenKeyboard()
        {
            var s = editableString == "" ? defaultString : editableString;
            try
            {
                Guide.BeginShowKeyboardInput(
                       PlayerIndex.One,
                       keyboardTitle,
                       keyboardDesc,
                       setEmptyTextArea ? "" : s,
                       new AsyncCallback(OnEndShowKeyboardInput),
                       null);
            }
            catch (Exception e)
            {
                e.ToString();
            }
        }
        private void OnEndShowKeyboardInput(IAsyncResult result)
        {
            if (result != null && Guide.EndShowKeyboardInput(result) != null)
            {
                //list[0].text = Guide.EndShowKeyboardInput(result);
                ExitSelector(Guide.EndShowKeyboardInput(result));
            }
        }

        Vector2 prev_drag_pos;
        float velocity = 0;
        void on_drag(Vector2 drag_pos)
        {
            if (prev_drag_pos != Vector2.Zero)
            {
                /*var distance = Vector2.Distance(drag_start_point, drag_pos) / 12;

                if (velocity == 0)
                    distance *= 2;
                if (drag_pos.Y > drag_start_point.Y)
                {
                    if (velocity < 0)
                        velocity = 0;
                    velocity += distance;
                    velocity = Math.Min(velocity, 40);
                }
                else
                {
                    if (velocity > 0)
                        velocity = 0;
                    velocity -= distance;
                    velocity = Math.Max(velocity, -40);
                }*/
                if (!RectContainsVect(dragArea, drag_pos))
                {
                    dragging = false;
                }
                else
                {
                    int offset = (int)(drag_pos.Y - prev_drag_pos.Y);
                    for (int i = 0; i < list.Count; i++)
                    {
                        list[i].rectangle.Y += offset;
                        list[i].UpdateTextPos();
                    }
                    velocity = offset;
                }
            }
            else
            {
                if (RectContainsVect(dragArea, drag_pos))
                {
                    dragging = true;
                }

            }
            prev_drag_pos = drag_pos;
        }
        void on_drag_completed()
        {
            prev_drag_pos = Vector2.Zero;
            dragging = false;
            if (velocity == 0 && list.Count > 0 && list[list.Count - 1].rectangle.Y + list[list.Count - 1].rectangle.Height > dragArea.Y + dragArea.Height)
                velocity = 0.01f;
        }

        public bool RectContainsVect(Rectangle rect, Vector2 v)
        {
            return rect.X < v.X && rect.Y < v.Y && rect.X + rect.Width > v.X && rect.Y + rect.Height > v.Y;
        }

        public override void SetPortraitOrientation()
        {
            list.Clear();
            upper_box = new MyButton(new Rectangle(0, 0, 480, 80), white, Color.Black);
            lower_box = new MyButton(new Rectangle(0, 750, 480, 50), white, Color.Black);
            if (isThereTextArea)
                list.Add(new MyButton(new Rectangle(20, upper_box.rectangle.Height, 440, 60), defaultString, Color.Black, font,
                    TextPos.Center, white, Color.LightGray));
            if(isThereTextArea2)
                list.Add(new MyButton(new Rectangle(20, upper_box.rectangle.Height+100, 440, 60), text2, Color.Black, font,
                    TextPos.Center, white, Color.LightGray));
            title = new MyButton(new Rectangle(20, 0, 200, 80), titleString, Color.White, font, TextPos.Left);
            //title.textScale = 0.5f;
            int offset = 0;
            if (isThereTextArea2)
                offset = 200;
            else if (isThereTextArea)
                offset = 100;
            for (int i = 0; i < itemsList.Count; i++)
            {
                var b = new MyButton(new Rectangle(20, upper_box.rectangle.Height + offset + i * 100, 440, 60), itemsList[i],
                   Color.White, font, textPos);//, white, Color.White);
                b.adjustVerticalAlignement = true;
                if (itemsList2.Count == itemsList.Count)
                {
                    b.text2 = itemsList2[i];
                    b.font2 = font;
                    b.textPos2 = textPos2;
                    b.textColor2 = Color.White;
                    b.UpdateTextPos();
                }
                list.Add(b);//, white, Color.White));
            }

            dragArea = new Rectangle(20, upper_box.rectangle.Height, 440, lower_box.rectangle.Y - upper_box.rectangle.Height);

            //titleEdit = new MyButton(new Rectangle(0, 100, 480, 100), defaultString + selectedItem, Color.White, titleFont);
            titleEdit = new MyButton(new Rectangle(0, 100, 480, 100), defaultString, Color.White, titleFont);
            if (selectedItem != null && selectedItem.Length >= 30)
                itemEdit = new MyButton(new Rectangle(0, 180, 480, 100), selectedItem, Color.White, smallFont);
            else
                itemEdit = new MyButton(new Rectangle(0, 180, 480, 100), selectedItem, Color.White, titleFont);
            cancelEdit = new MyButton(new Rectangle(260, 300, 50, 50), cancel, Color.White, circle, Color.White);
            confirmEdit = new MyButton(new Rectangle(170, 300, 50, 50), confirm, Color.White, circle, Color.White);
        }

        public override void SetLandScapeOrientation()
        {
            list.Clear();
            upper_box = new MyButton(new Rectangle(0, 0, 800, 80), white, Color.Black);
            lower_box = new MyButton(new Rectangle(0, 440, 800, 40), white, Color.Black);
            if (isThereTextArea)
                list.Add(new MyButton(new Rectangle(100, upper_box.rectangle.Height, 600, 60), defaultString, Color.Black, font,
                    TextPos.Center, white, Color.LightGray));
            if (isThereTextArea2)
                list.Add(new MyButton(new Rectangle(100, upper_box.rectangle.Height + 100, 600, 60), text2, Color.Black, font,
                    TextPos.Center, white, Color.LightGray));
            title = new MyButton(new Rectangle(100, 0, 200, 80), titleString, Color.White, font, TextPos.Left);
            //title.textScale = 0.5f;
            int offset = 0;
            if (isThereTextArea2)
                offset = 200;
            else if (isThereTextArea)
                offset = 100;
            for (int i = 0; i < itemsList.Count; i++)
            {
                var b = new MyButton(new Rectangle(100, upper_box.rectangle.Height + offset + i * 100, 600, 60), itemsList[i],
                   Color.White, font, textPos);
                b.adjustVerticalAlignement = true;
                if (itemsList2.Count == itemsList.Count)
                {
                    b.text2 = itemsList2[i];
                    b.font2 = font;
                    b.textPos2 = textPos2;
                    b.textColor2 = Color.White;
                    b.UpdateTextPos();
                }
                list.Add(b);//, white, Color.White));
            }

            dragArea = new Rectangle(20, upper_box.rectangle.Height, 760, lower_box.rectangle.Y - upper_box.rectangle.Height);

            //titleEdit = new MyButton(new Rectangle(0, 100, 800, 100), defaultString + selectedItem, Color.White, titleFont);
            titleEdit = new MyButton(new Rectangle(0, 100, 800, 100), defaultString, Color.White, titleFont);
            if (selectedItem != null && selectedItem.Length >= 30)
                itemEdit = new MyButton(new Rectangle(0, 180, 800, 100), selectedItem, Color.White, smallFont);
            else
                itemEdit = new MyButton(new Rectangle(0, 180, 800, 100), selectedItem, Color.White, titleFont);

            cancelEdit = new MyButton(new Rectangle(420, 300, 50, 50), cancel, Color.White, circle, Color.White);
            confirmEdit = new MyButton(new Rectangle(330, 300, 50, 50), confirm, Color.White, circle, Color.White);
        }
        public void ExitSelector(String result)
        {
            if (!editingList)
            {
                Game.Components.Remove(input_manager);
                Game.Components.Remove(this);
                closeSelector(result);
            }
            else
            {
                openPopUp = true;
                selectedItem = result;
                titleEdit.text = defaultString;// +result;
                itemEdit.text = result;
                if (result != null && result.Length >= 30)
                    itemEdit.font = smallFont;
                else
                    itemEdit.font = titleFont;
            }
        }

    }
}
